<?php
declare(strict_types=1);

namespace app\shop\logic;

use app\shop\enums\goods\GoodsStatus;
use app\shop\exception\FailException;
use app\shop\exception\ParamsErrorException;
use app\shop\library\ShopAuth;
use app\shop\model\goods\GoodsSkuModel;
use app\shop\model\user\UserCartModel;
use Exception;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException as DbExceptionAlias;
use think\db\exception\ModelNotFoundException;
use think\Model;
use Throwable;

/**
 * @property UserCartModel $model
 */
class UserCartLogic extends BaseLogic
{
    public function __construct()
    {
        $this->model = new UserCartModel();
    }

    /**
     * 列表
     * @param array $params
     * @return array
     * @throws DbExceptionAlias
     */
    public function list(array $params): array
    {
        $query = UserCartModel::getQuery();

        $query->where(['user_id' => $params['user_id']]);

        $result = $query->field(['id', 'goods_id', 'sku_id', 'num', 'old_price', 'selected'])
            ->with([
                'goods' => function ($query) {
                    $query->field(['id', 'name', 'delete_time', 'status']);
                },
                'sku'   => function ($query) {
                    $query->withTrashed()->field(['id', 'spec', 'price', 'stock', 'image', 'delete_time'])
                        ->append(['spec_text']);
                }
            ])->paginate()->each(function ($item) {
                if (!$item->goods || !$item->sku) {
                    unset($item);   //移除无效的购物车记录
                } elseif ($item->goods->delete_time > 0 || $item->sku->delete_time > 0 || $item->goods->status == GoodsStatus::OFF_SHELF) {
                    $item['disabled']      = true;
                    $item['disabled_text'] = '下架';
                } elseif ($item->sku->stock <= 0) {
                    $item['disabled']      = true;
                    $item['disabled_text'] = '无货';
                } else {
                    $item['disabled']      = false;
                    $item['disabled_text'] = '';
                }
            })->toArray();

        $result['total_effective_num'] = count(
            (array_filter($result['data'], function ($item) {
                return $item['disabled'] == false;
            }))
        );

        $result['total_num'] = array_sum(array_column($result['data'], 'num'));

        return $result;
    }

    /**
     * 添加
     * @param array $params
     * @return array
     * @throws FailException
     * @throws ParamsErrorException
     */
    public function add(array $params): array
    {
        $skuInfo = $this->getSkuInfo($params['sku_id'], $params['num']);
        try {
            $cartInfo = UserCartModel::where([
                'sku_id'  => $params['sku_id'],
                'user_id' => $params['user_id'],
            ])->with(['sku'])->findOrEmpty();

            if ($cartInfo->isEmpty()) {
                $cartInfo = UserCartModel::create([
                    'user_id'   => ShopAuth::instance()->__get('id'),
                    'goods_id'  => $skuInfo->goods->id,
                    'sku_id'    => $params['sku_id'],
                    'num'       => $params['num'],
                    'old_price' => $skuInfo['price'],
                    'selected'  => 1
                ]);
            } else {
                // 更新数量
                $cartInfo->num      += $params['num'];
                $cartInfo->selected = 1;
                $cartInfo->save();
            }
        } catch (Exception $e) {
            throw new FailException('添加失败', null, $e);
        }

        $result = $cartInfo->toArray();

        $result['total_num'] = $this->model->where('user_id', $params['user_id'])->sum('num');

        return $result;
    }

    /**
     * 修改
     * @param array $params
     * @return array
     * @throws FailException|ParamsErrorException
     */
    public function update(array $params): array
    {
        $cartInfo = UserCartModel::where(['id' => $params['id'], 'user_id' => $params['user_id']])->findOrEmpty();
        if ($cartInfo->isEmpty()) {
            throw new ParamsErrorException('购物车记录不存在,请刷新');
        }
        try {
            $cartInfo->num      = $params['num'] ?? $cartInfo->num;
            $cartInfo->selected = $params['selected'] ?? $cartInfo->selected;
            $cartInfo->save();
        } catch (Exception $e) {
            throw new FailException('编辑失败', null, $e);
        }

        return $cartInfo->toArray();
    }

    /**
     * 删除
     * @param array $params
     * @return bool
     * @throws FailException|ParamsErrorException
     */
    public function delete(array $params): bool
    {
        $cartInfo = UserCartModel::where(['id' => $params['id'], 'user_id' => $params['user_id']])->findOrEmpty();
        if ($cartInfo->isEmpty()) {
            throw new ParamsErrorException('购物车记录已被删除,请刷新');
        }
        try {
            $cartInfo->delete();

            return true;
        } catch (Throwable $e) {
            throw new FailException('删除失败', null, $e);
        }
    }

    /**
     * 清空
     * @param array $params
     * @return bool
     * @throws DbExceptionAlias
     * @throws FailException
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     */
    public function clear(array $params): bool
    {
        $cartInfo = UserCartModel::where(['user_id' => $params['user_id']])->select();
        if ($cartInfo->isEmpty()) {
            return true;
        }

        try {
            UserCartModel::where(['user_id' => $params['user_id']])->delete();

            return true;
        } catch (Throwable $e) {
            throw new FailException('清空失败', null, $e);
        }
    }

    /**
     * 获取sku信息
     * @param int|string $skuId
     * @param int|string $num
     * @return GoodsSkuModel|array|mixed|Model
     * @throws ParamsErrorException
     */
    private function getSkuInfo(int|string $skuId, int|string $num): mixed
    {
        $skuInfo = GoodsSkuModel::where(['id' => $skuId])
            ->with(['goods'])
            ->findOrEmpty();
        if ($skuInfo->isEmpty()) {
            throw new ParamsErrorException('商品规格已下架');
        }
        if ($skuInfo['stock'] < $num) {
            throw new ParamsErrorException('商品库存不足');
        }

        return $skuInfo;
    }

    /**
     * 全选
     * @param array $params
     * @return true
     */
    public function selectAll(array $params): bool
    {
        $selected = (bool)$params['selected'];

        UserCartModel::where(['user_id' => $params['user_id']])->update(['selected' => $selected]);

        return true;
    }

    /**
     * 获取购物车总数
     * @param array $params
     * @return float
     */
    public function getTotalNum(array $params): float
    {
        return $this->model->where('user_id', $params['user_id'])->sum('num');
    }
}
